
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package client.gui.controls.scrabble;

import client.gui.controls.kleurschema.Kleurenschemas;
import client.controllers.ScrabbleController;
import client.controllers.DragAndDropVerifier;
import client.data.BlokjeTransferable;
import java.awt.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;
import java.io.Serializable;
import javax.swing.*;
import org.apache.log4j.Logger;
import client.communication.ClientCommunication;

/**
 *
 * @author Liesbeth
 */
public class Blokje extends JLabel implements Serializable {

    private Logger logger = Logger.getLogger(Blokje.class);
    private int miWaarde;
    private String msLetter;    
    private Font mfDefaultFont = new Font("Tahoma", 1, 26);
    private boolean mbBlancoBlokje = false;
    private boolean gevalideerd = false;
    private boolean dragable = false;
    private Point oldPosition;
    // private boolean mbGelegd = false;
    private DragSource dragSource;
    private DragGestureListener dgListener;
    private DragSourceListener dsListener;
    private int dragAction = DnDConstants.ACTION_MOVE;

    public Blokje(String s) {
        this.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        this.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        this.setBackground(getDefaultBackground());
        this.setFont(getDefaultFont());
        this.setForeground(getDefaultForeground());
        this.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED, null, new java.awt.Color(255, 204, 153), null, null));
        this.setOpaque(true);
        this.addMouseListener(new java.awt.event.MouseAdapter() {

            public void mousePressed(java.awt.event.MouseEvent e) {
                myMousePressed(e);
            }

            public void mouseReleased(java.awt.event.MouseEvent e) {
                myMouseReleased(e);
            }
        });
        this.addMouseListener(new java.awt.event.MouseAdapter() {

            public void mouseEntered(java.awt.event.MouseEvent e) {
                myMouseEntered(e);
            }
        });
        setLetter(s);

        this.dragSource = DragSource.getDefaultDragSource();
        this.dgListener = new DGListener();
        this.dsListener = new DSListener();

        // component, action, listener
        this.dragSource.createDefaultDragGestureRecognizer(this, this.dragAction, this.dgListener);

    }

    public void myMouseEntered(java.awt.event.MouseEvent e) {
        if (!this.isGevalideerd()) {
            this.setCursor(new Cursor(Cursor.HAND_CURSOR));
        } else {
            this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        }
    }

    public void myMousePressed(java.awt.event.MouseEvent e) {
        //Als het blokje al gevalideerd is, mag je er niet meer op kunnen klikken
        if (!this.isGevalideerd()) {
            this.setBackground(getDefaultSelectionColor());
            if (e.getClickCount() == 2) {
                String s = this.getText();
                if (isBlancoBlokje()) {
                    String str[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
                        "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
                    };

                    s = (String) JOptionPane.showInputDialog(this.getParent().getParent().getParent().getParent(), "Kies een letter:", "Wildchar", 1, null, str, "A");
                    if (s != null && !s.equals("")) {
                        this.setLetter(s);
                        this.setWaarde(ClientCommunication.getInstance().getLetterWaardes().get(s));
                    }
                    Point nieuwePositie;
                    Hokje h = (Hokje) Blokje.this.getParent();
                    if (!(h.getParent() instanceof Plankje)) {
                        nieuwePositie = h.getLocatie();
                        String gameNaam = ClientCommunication.getInstance().getGameNaam();
                        ClientCommunication.getInstance().verplaatsBlokjeOpSpelbord(nieuwePositie, this.getOldPosition(), this.getLetter(), this.isBlancoBlokje(), gameNaam);
                    }

                    //mouseReleased oproepen om te forceren dat het blokje niet
                    //geselecteerd blijft staan na het klikken op OK/Cancel
                    myMouseReleased(e);

                }
            }
        }
    }

    public void myMouseReleased(java.awt.event.MouseEvent e) {
        if (!this.isGevalideerd()) {
            this.setBackground(getDefaultBackground());
        }
    }

    public int getWaarde() {
        return miWaarde;
    }

    public void setWaarde(int miWaarde) {
        this.miWaarde = miWaarde;
        this.setToolTipText("Puntenwaarde letter: " + miWaarde);
    }

    public String getLetter() {
        return msLetter;
    }

    public void setLetter(String sLetter) {
        this.msLetter = sLetter;
        this.setText(sLetter);
    //this.setWaarde(BlokjesVerdeler.getInstance().getLetterWaarde(sLetter));
    }

    public Color getDefaultBackground() {
        return Kleurenschemas.getInstance().blokjeKleur;
    }

    public Color getDefaultForeground() {
        return Kleurenschemas.getInstance().fontBlokjeKleur;
    }

    public Font getDefaultFont() {
        return mfDefaultFont;
    }

    public Color getDefaultSelectionColor() {
        return Kleurenschemas.getInstance().selecteerKleur;
    }

    public boolean isBlancoBlokje() {
        return mbBlancoBlokje;
    }

    public void setBlancoBlokje(boolean bBlancoBlokje) {
        this.mbBlancoBlokje = bBlancoBlokje;
        if (isBlancoBlokje()) {
            this.setForeground(Kleurenschemas.getInstance().blankBlokjeKleur);
        }
    }

    public boolean isGevalideerd() {
        return gevalideerd;
    }

    public void setGevalideerd(boolean gevalideerd) {
        this.gevalideerd = gevalideerd;
        if (gevalideerd) {
            this.setBackground(Kleurenschemas.getInstance().gevalideerdBlokjeKleur);
            this.setForeground(Kleurenschemas.getInstance().gevalideerdFontBlokjeKleur);
        } else {
            this.setBackground(Kleurenschemas.getInstance().blokjeKleur);
            this.setForeground(Kleurenschemas.getInstance().fontBlokjeKleur);
            //
            if (isBlancoBlokje()) {
                setBlancoBlokje(isBlancoBlokje());
            }
        }
    }

    public Point getOldPosition() {
        return oldPosition;
    }

    public void setOldPosition(Point oldPosition) {
        this.oldPosition = oldPosition;
    }

    public boolean isDragable() {
        return dragable;
    }

    @Override
    public String toString() {
        return getLetter();
    }

    public void setDragable(boolean dragable) {
        this.dragable = dragable;
    }

    public void bepaalLayout() {
        if (gevalideerd) {
            this.setBackground(Kleurenschemas.getInstance().gevalideerdBlokjeKleur);
            this.setForeground(Kleurenschemas.getInstance().gevalideerdFontBlokjeKleur);
        } else {
            this.setBackground(Kleurenschemas.getInstance().blokjeKleur);
            this.setForeground(Kleurenschemas.getInstance().fontBlokjeKleur);
            //
            if (isBlancoBlokje()) {
                this.setBackground(Kleurenschemas.getInstance().blokjeKleur);
                this.setForeground(Kleurenschemas.getInstance().blankBlokjeKleur);
            }
        }
    }

    //Een listener die het slepen zal starten
    class DGListener implements DragGestureListener {

        // Methode die het slepen opvangt
        public void dragGestureRecognized(DragGestureEvent e) {
            // Als de sleepactie OK is, doen we verder, zoniet doen we niks
            // Als het blokje gevalideerd is, mag je het ook niet verslepen
            //if (Blokje.this.isDragable() && !Blokje.this.isGevalideerd() && (e.getDragAction() & Blokje.this.dragAction) != 0) {
            if (!Blokje.this.isGevalideerd() && (e.getDragAction() & Blokje.this.dragAction) != 0) {
                logger.debug("Start slepen van blokje");

                Transferable transferable = null;
                try {
                    Blokje b = new Blokje(Blokje.this.getLetter());
                    Hokje h = (Hokje) Blokje.this.getParent();
                    //oude positie bijhouden van het blokje om zo te weten of er een nieuw blokje geplaatst is
                    //of er een ander blokje egwoon verplaatst is
                    b.setOldPosition(h.getLocatie());//wanneer het blokje nog op het plankje staat zal dit null zijn
                    b.setBlancoBlokje(Blokje.this.isBlancoBlokje());
                    b.setGevalideerd(Blokje.this.isGevalideerd());
                    b.setWaarde(Blokje.this.getWaarde());
                    transferable = new BlokjeTransferable(b);
                } catch (ClassNotFoundException cnfex) {
                    logger.error("DataFlavor class not found for dragging Blokje!");
                }

                // start het slepen
                try {
                    // parameters: cursor, transferrable, dragsource listener
                    e.startDrag(DragSource.DefaultLinkNoDrop, transferable, Blokje.this.dsListener);
                } catch (InvalidDnDOperationException idoe) {
                    logger.error("Fout tijdens het slepen van een blokje!");
                    logger.error(idoe.getMessage());
                }
            }
        }
    }


    //Een listener die de status van de Drag en Drop operatie zal volgen
    class DSListener implements DragSourceListener {

        // Methode die het droppen opvangt
        public void dragDropEnd(DragSourceDropEvent e) {

            if (e.getDropSuccess() == false) {
                logger.debug("Het droppen van het blokje is mislukt!");
            } else {
                // Als de actie van het drop target gelijk is aan "MOVE", 
                // het blokje op het spelbord zetten

                if (DragAndDropVerifier.getInstance().isDropOpVakje() && e.getDropAction() == DnDConstants.ACTION_MOVE) {
                    Blokje.this.setVisible(false);
                    Hokje vp = (Hokje) Blokje.this.getParent();
                    vp.setVakjeOfBlokje(vp.getVakje());
                    if (!(vp.getParent() instanceof Plankje)) {
                        //Enkel een bezet vakje verwijderen als je sleept vanaf het spelbor d
                        //en niet vanaf het plankje
                        ScrabbleController.getInstance().removeBezetVakje(vp.getLocatie());
                    }

                    DragAndDropVerifier.getInstance().setDropOpVakje(false);
                }
            }
        }

        public void dragEnter(DragSourceDragEvent e) {
            DragSourceContext context = e.getDragSourceContext();

            //Intersectie van de gekozen actie, en de drag source en drag target acties
            if ((e.getDropAction() & Blokje.this.dragAction) != 0) {
                context.setCursor(DragSource.DefaultCopyDrop);
            } else {
                context.setCursor(DragSource.DefaultCopyNoDrop);
            }
        }

        public void dragOver(DragSourceDragEvent e) {
        }

        public void dragExit(DragSourceEvent e) {
        }

        public void dropActionChanged(DragSourceDragEvent e) {
        }
    }
}
